<!DOCTYPE html>
<!-- saved from url=(0040)https://imququ.com/post/web-proxy-2.html -->
<html lang="zh-CN">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
		<meta name="format-detection" content="telephone=no">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<title>HTTP 代理原理及实现（二） | JerryQu 的小站</title>
		<meta name="theme-color" content="#007b8b">
		<meta name="mobile-web-app-capable" content="yes">
		<meta name="application-name" content="JerryQu 的小站">
		<meta name="msapplication-starturl" content="https://imququ.com">
		<meta name="msapplication-navbutton-color" content="#007b8b">
		<meta name="apple-mobile-web-app-capable" content="yes">
		<meta name="apple-mobile-web-app-title" content="JerryQu 的小站">
		<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
		<link rel="apple-touch-icon" href="https://st.imququ.com/static/img/blog/icon.png">
		<link rel="manifest" href="https://imququ.com/static/manifest.json">
		<link rel="search" type="application/opensearchdescription+xml" href="https://imququ.com/opensearch.xml"
			title="JerryQu 的小站">
		<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="https://imququ.com/rss.html">
		<style>
			* {
				margin: 0;
				padding: 0
			}

			html,
			body {
				height: 100%
			}

			body {
				background: #ddd;
				color: #666;
				font-size: 14px;
				font-family: Roboto, Helvetica, Tahoma, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK", "WenQuanYi Micro Hei", sans-serif;
				-webkit-font-smoothing: antialiased
			}

			::selection,
			::-moz-selection,
			::-webkit-selection {
				background-color: #2479CC;
				color: #eee
			}

			h1 {
				font-size: 2em
			}

			h3 {
				font-size: 1.3em
			}

			h4 {
				font-size: 1.1em
			}

			a {
				text-decoration: none;
				color: #076dd0
			}

			article {
				border-bottom: 1px solid #ddd;
				border-top: 1px solid #fff;
				position: relative;
				padding: 30px 0
			}

			.container {
				position: relative;
				min-height: 100%;
				max-width: 1600px
			}

			.left-col {
				width: 270px;
				position: fixed;
				height: 100%;
				background-color: #007b8b;
				background-image: url(https://st.imququ.com/static/img/blog/left-bg2.jpg);
				background-size: cover
			}

			.mid-col {
				position: absolute;
				left: 0;
				right: 0;
				min-height: 100%;
				margin-left: 270px;
				background: #fff
			}

			article .meta {
				position: relative;
				float: right;
				color: #555;
				font-size: .9em;
				line-height: 2;
				width: auto;
				text-align: right
			}

			article .entry-content,
			article .meta a {
				color: #444
			}

			article .entry-content {
				font-size: 16px;
				line-height: 1.8;
				word-wrap: break-word
			}

			article h1.title {
				color: #333;
				font-size: 2em;
				font-weight: 400;
				line-height: 35px;
				margin-bottom: 25px
			}

			article .entry-content p {
				margin-top: 15px
			}

			article h1.title a {
				color: #333;
				transition: color .3s
			}

			.mid-col .mid-col-container {
				padding: 0 70px 0 40px
			}

			article .meta .date,
			article .meta .comment,
			article .meta .tags {
				position: relative
			}

			article .meta .date-modified {
				display: none
			}

			article .entry-content a:hover {
				text-decoration: underline
			}

			article h1.title a:hover {
				color: #076dd0
			}

			#header {
				width: 100%;
				line-height: 30px;
				height: auto;
				border-bottom: none;
				padding: 30px 0;
				margin-left: 50px
			}

			#main-nav,
			#sub-nav {
				float: none;
				margin-top: 15px
			}

			#main-nav {
				margin-left: 0
			}

			#sub-nav {
				position: relative
			}

			#content {
				width: 100%;
				margin: 0 auto
			}

			#footer {
				line-height: 2.2;
				text-align: center;
				width: auto;
				padding: 15px 70px 15px 40px;
				border-top: 1px solid #fff;
				font-size: .9em
			}

			#header a {
				color: #fff;
				text-shadow: 0 1px #666;
				transition: color .3s
			}

			#header h1 {
				font-weight: 400;
				font-size: 30px;
				float: none
			}

			#main-nav ul li {
				margin-left: 0;
				display: block;
				position: relative
			}

			#header .subtitle {
				color: #fff
			}

			#sub-nav .social {
				margin-bottom: 10px
			}

			#footer .beian {
				color: #666
			}

			#header a:hover {
				color: #ccc
			}

			#header .profilepic a {
				display: block;
				width: 160px;
				height: 160px;
				border-radius: 50%;
				background-image: url();
				background-size: 100% 100%;
				margin: 15px 0 20px -10px
			}

			#sub-nav .social a {
				border-radius: 50%;
				display: inline-block;
				vertical-align: middle;
				text-indent: -9999px;
				margin: 0 6px 15px;
				width: 28px;
				height: 28px;
				background-size: 20px 20px;
				background-position: center center;
				background-repeat: no-repeat;
				opacity: .75;
				transition: opacity .3s
			}

			#sub-nav .social a:hover {
				opacity: 1
			}

			#sub-nav .social a:first-of-type {
				margin-left: 0
			}

			#sub-nav .social a:last-of-type {
				margin-right: 0
			}

			#sub-nav .social a.twitter {
				background-image: url();
				background-color: #55cff8;
				border: 1px solid #55CFF8
			}

			#sub-nav .social a.search {
				background-image: url();
				background-color: #afb6ca;
				border: 1px solid #afb6ca
			}

			#sub-nav .social a.rss {
				background-image: url();
				background-color: #ef7522;
				border: 1px solid #ef7522
			}

			#sub-nav .social a.twitter:hover {
				border: 1px solid #24c1f6
			}

			#sub-nav .social a.search:hover {
				border: 1px solid #909ab6
			}

			#sub-nav .social a.rss:hover {
				border: 1px solid #cf5d0f
			}

			@media screen and (max-width:1024px) {
				article {
					padding-bottom: 15px
				}

				.left-col {
					width: 210px
				}

				.mid-col {
					margin-left: 210px
				}

				article h1.title,
				article .entry-content {
					margin-left: 0
				}

				.mid-col .mid-col-container {
					padding: 0 20px
				}

				#header {
					margin-left: 30px
				}

				#footer {
					padding: 15px 20px
				}
			}

			@media screen and (max-width:640px) {
				article {
					padding: 20px 0
				}

				.left-col {
					position: relative;
					width: 100%;
					background-image: none
				}

				.mid-col {
					margin-left: 0;
					float: none;
					width: 100%
				}

				article .meta {
					margin-bottom: 10px;
					position: static;
					width: auto
				}

				.mid-col .mid-col-container {
					padding: 0 10px
				}

				.total_thread .tips {
					display: block;
					margin-top: 10px
				}

				.mid-col article .meta {
					float: none;
					overflow: hidden
				}

				article .meta .date,
				article .meta .comment,
				article .meta .tags {
					display: inline;
					margin-right: 5px;
					padding-left: 0
				}

				article .meta .date {
					margin-right: 30px
				}

				#header {
					padding: 20px 0;
					margin-left: 0;
					text-align: center
				}

				#main-nav {
					margin-top: 10px
				}

				#footer {
					padding: 15px 10px
				}

				#main-nav ul li {
					display: inline;
					margin: 0 10px;
					text-align: center
				}

				#header .profilepic a {
					position: absolute;
					top: 12px;
					left: 12px;
					width: 56px;
					height: 56px;
					margin: 0
				}

				#sub-nav .social,
				#sub-nav .social a {
					margin-bottom: 0
				}

				#sub-nav .social a {
					opacity: 1
				}

				#content #toc-container,
				#content #toc {
					float: none
				}

				#content #toc {
					max-width: 100%;
					margin: 0
				}
			}

			article input.runcode,
			article button {
				line-height: 1;
				border: none;
				cursor: pointer;
				padding: .625em .5em;
				border-radius: 0;
				box-shadow: inset 0 -5px 20px rgba(0, 0, 0, .1);
				background: #12b0e6;
				color: #fff;
				font-size: 14px;
				margin-top: 10px;
				-webkit-appearance: none
			}

			article button {
				margin-top: 0
			}

			article strong {
				font-weight: 700
			}

			article em {
				font-style: italic
			}

			article blockquote {
				margin-top: 10px;
				padding: 15px 20px;
				border-left: 5px solid #2479CC;
				background-color: #f8f8f8;
				overflow: hidden
			}

			article code {
				font-family: Consolas, Monaco, 'Andale Mono', monospace;
				font-size: 80%;
				margin: 0 2px;
				padding: 4px 5px;
				background-color: #eee;
				vertical-align: middle;
				border-radius: 5px
			}

			article pre {
				font-size: 14px;
				line-height: 1.6;
				color: #5d6a6a;
				padding: .6em;
				border-left: 5px solid #ccc;
				background-color: #f8f8f8;
				word-break: break-word;
				word-wrap: break-word;
				white-space: pre-wrap;
				position: relative;
				overflow: hidden
			}

			article img {
				padding: 0;
				display: block;
				border: 1px solid #ccc;
				margin: 10px 0 5px 0;
				max-width: 100%
			}

			article table {
				border: 0;
				border-collapse: collapse;
				border-spacing: 0
			}

			article pre code {
				border-radius: 0 0 0 0;
				background-color: transparent;
				border: 0;
				padding: 0;
				margin: 0;
				font-size: 100%;
				display: block;
				position: relative
			}

			article table th,
			article table td {
				border: 0
			}

			article table th {
				border-bottom: 2px solid #848484;
				text-align: left;
				padding: 6px 20px
			}

			article table td {
				border-bottom: 1px solid #d0d0d0;
				padding: 6px 20px
			}

			.total_thread {
				line-height: 1.6
			}

			.page-navi {
				width: 100%;
				line-height: 20px;
				position: relative;
				border-top: 1px solid #fff;
				border-bottom: 1px solid #ddd;
				padding: 20px 0;
				overflow: hidden
			}

			article .copyright-info {
				font-size: 14px
			}

			article .expired-tips {
				padding: 5px 10px;
				font-size: 15px;
				border: 1px solid #e2e2e2;
				background-color: #ffffc0;
				border-left: 5px solid #fff000;
				color: #333;
				overflow: hidden
			}

			article .post-info {
				font-size: 14px
			}

			article.post-search {
				padding-bottom: 0
			}

			article input.runcode:hover,
			article input.runcode:focus,
			article input.runcode:active,
			article button:hover,
			article button:focus,
			article button:active {
				background: #f6ad08
			}

			article img.loaded {
				height: auto !important
			}

			article .entry-content blockquote,
			article .entry-content ul,
			article .entry-content ol,
			article .entry-content dl,
			article .entry-content table,
			article .entry-content iframe,
			article .entry-content h1,
			article .entry-content h2,
			article .entry-content h3,
			article .entry-content h4,
			article .entry-content h5,
			article .entry-content h6,
			article .entry-content pre {
				margin-top: 15px
			}

			article .entry-content ul,
			article .entry-content ol,
			article .entry-content dl {
				margin-left: 25px
			}

			article pre b.name {
				font-family: "Consolas", "Liberation Mono", Courier, monospace;
				position: absolute;
				line-height: 1;
				top: 10px;
				right: 10px;
				font-size: 60px;
				color: #eee;
				pointer-events: none
			}

			article .entry-content .date {
				color: #666;
				font-size: 14px
			}

			article .entry-content ul ul,
			article .entry-content ul ol,
			article .entry-content ul dl,
			article .entry-content ol ul,
			article .entry-content ol ol,
			article .entry-content ol dl,
			article .entry-content dl ul,
			article .entry-content dl ol,
			article .entry-content dl dl,
			article .entry-content blockquote>p:first-of-type {
				margin-top: 0
			}

			#comments {
				border-top: 1px solid #fff;
				border-bottom: 1px solid #ddd;
				padding: 20px 0;
				min-height: 350px
			}

			#comments h1.title {
				font-size: 25px;
				font-weight: 400;
				line-height: 35px;
				margin-bottom: 10px
			}

			.total_thread .tips {
				color: #888
			}

			.page-navi .prev {
				float: left
			}

			.page-navi .next {
				float: right
			}

			.page-navi .center {
				text-align: center;
				width: 80px;
				margin: auto
			}

			#searchResult {
				min-height: 350px
			}

			#search form {
				position: relative
			}

			#search .wrapper {
				margin-right: 72px
			}

			#search .submit {
				-webkit-appearance: none;
				background-color: #e7e7e7;
				border: 1px solid #bbb;
				border-left: 0;
				border-radius: 0;
				color: #222;
				display: block;
				font-size: 16px;
				height: 40px;
				outline: 0;
				position: absolute;
				right: 0;
				top: 0;
				width: 72px
			}

			#searchResult .info {
				color: #676767;
				font-size: 13px;
				padding: 15px 0;
				border-bottom: 1px solid #ddd
			}

			#searchResult .no-result {
				padding: 5px;
				margin: 15px 0;
				border: 1px solid #fc3;
				background-color: #fff4c2;
				font-size: 13px
			}

			#searchResult .loading,
			#searchResult .hot-words {
				margin-top: 20px
			}

			#searchResult .item {
				padding: 10px 0 20px;
				border-bottom: 1px solid #ddd
			}

			#search .wrapper input {
				-webkit-appearance: none;
				border: 1px solid #bbb;
				border-radius: 0;
				box-sizing: border-box;
				display: block;
				font-size: 16px;
				height: 40px;
				outline: 0;
				padding: 4px 6px;
				width: 100%;
				background-color: #fff
			}

			#searchResult .hot-words a {
				margin-right: 20px
			}

			#searchResult .item:last-of-type {
				border-bottom: 0
			}

			#searchResult .item .title {
				margin: 5px 0
			}

			#searchResult .item .desc {
				font-size: 14px;
				overflow: hidden
			}

			#searchResult .item .img {
				width: 108px;
				height: 81px;
				border: 1px solid #ccc;
				float: left;
				margin: 4px 8px 0 0
			}

			#searchResult .item .title a {
				font-size: 17px
			}

			#searchResult .item .img img {
				width: 100%;
				border: 0;
				margin: 0
			}

			#searchResult .item .title .type {
				display: inline-block;
				background-color: #eee;
				color: #888;
				margin-right: 6px;
				padding: 0 4px;
				font-size: 12px;
				border-radius: 3px;
				position: relative;
				top: -1px
			}

			.hljs-comment,
			.diff .hljs-header,
			.hljs-doctype,
			.hljs-pi,
			.lisp .hljs-string,
			.hljs-javadoc {
				color: #999
			}

			.hljs-keyword,
			.hljs-winutils,
			.method,
			.hljs-addition,
			.css .hljs-tag,
			.hljs-request,
			.hljs-status,
			.nginx .hljs-title {
				color: #859900
			}

			.hljs-number,
			.hljs-command,
			.hljs-string,
			.hljs-tag .hljs-value,
			.hljs-rule .hljs-value,
			.hljs-phpdoc,
			.hljs-dartdoc,
			.tex .hljs-formula,
			.hljs-regexp,
			.hljs-hexcolor,
			.hljs-link_url {
				color: #2aa198
			}

			.hljs-title,
			.hljs-localvars,
			.hljs-chunk,
			.hljs-decorator,
			.hljs-built_in,
			.hljs-identifier,
			.vhdl .hljs-literal,
			.hljs-id,
			.css .hljs-function,
			.hljs-name {
				color: #268bd2
			}

			.hljs-attribute,
			.hljs-variable,
			.lisp .hljs-body,
			.smalltalk .hljs-number,
			.hljs-constant,
			.hljs-class .hljs-title,
			.hljs-parent,
			.hljs-type,
			.hljs-link_reference {
				color: #b58900
			}

			.hljs-preprocessor,
			.hljs-preprocessor .hljs-keyword,
			.hljs-pragma,
			.hljs-shebang,
			.hljs-symbol,
			.hljs-symbol .hljs-string,
			.diff .hljs-change,
			.hljs-special,
			.hljs-attr_selector,
			.hljs-subst,
			.hljs-cdata,
			.css .hljs-pseudo,
			.hljs-header {
				color: #cb4b16
			}

			.hljs-deletion,
			.hljs-important {
				color: #dc322f
			}

			.hljs-link_label {
				color: #6c71c4
			}

			.tex .hljs-formula {
				background: #eee8d5
			}

			#toc-container,
			#toc {
				float: right
			}

			#toc {
				min-width: 120px;
				max-width: 260px;
				padding: 6px;
				margin: 0 0 15px 20px;
				border: 1px solid #e2e2e2;
				font-size: 14px
			}

			#toc strong {
				border-bottom: 1px solid #e2e2e2;
				display: block
			}

			#toc p {
				padding: 0 4px;
				margin: 0
			}

			#toc ul {
				margin: .5em .5em .5em 1.5em
			}

			#simple_thread ol,
			#simple_thread ul {
				list-style: none;
				list-style-type: none
			}

			#toc ul ul {
				margin-top: 0;
				margin-bottom: 0
			}

			#simple_thread>.thread {
				font-family: "Helvetica Neue", arial, sans-serif;
				-webkit-font-smoothing: antialiased;
				-moz-osx-font-smoothing: grayscale;
				color: #2a2e2e
			}

			#simple_thread .thread-new {
				margin-bottom: 20px
			}

			#simple_thread .avatar {
				float: left
			}

			#simple_thread .nav {
				position: relative;
				margin: 0 0 20px;
				border-bottom: 2px solid #e7e9ee
			}

			#simple_thread .tab-conversation {
				float: left
			}

			#simple_thread .btn {
				border: none;
				background: #778289;
				background: rgba(29, 47, 58, .6);
				display: inline-block;
				padding: 10px 16px;
				color: #fff;
				line-height: 1.1;
				border-radius: 3px;
				font-weight: 500;
				transition: background .2s;
				text-shadow: none
			}

			#simple_thread .post-content {
				position: relative;
				margin-bottom: 24px;
				transition: all .2s ease-in-out
			}

			#simple_thread .post-body {
				overflow: hidden
			}

			#simple_thread .clearfix:after,
			#simple_thread .clearfix:before {
				display: table;
				content: "";
				line-height: 0;
				clear: both
			}

			#simple_thread .publisher-anchor-color a {
				color: #2479cc !important
			}

			#searchResult .item .summary {
				display: block;
				line-height: 22px;
				max-height: 88px
			}

			#simple_thread .thread-new .create-post {
				line-height: 1;
				border: none;
				cursor: pointer;
				padding: .625em .5em;
				border-radius: 0;
				box-shadow: inset 0 -5px 20px rgba(0, 0, 0, .1);
				background: #12b0e6;
				color: #fff;
				font-size: 14px;
				-webkit-appearance: none;
				margin-right: 10px
			}

			#simple_thread .avatar .user,
			#simple_thread .avatar img {
				display: block;
				border-radius: 3px
			}

			#searchResult .item .title b,
			#searchResult .item .desc b {
				color: #C00;
				font-weight: 400
			}

			#simple_thread .active .publisher-nav-color::after {
				background-color: #076dd0 !important
			}

			#simple_thread .avatar img {
				width: 48px;
				height: 48px
			}

			#simple_thread .avatar .user {
				position: relative;
				z-index: 100;
				background: #dbdfe4;
				padding: 0
			}

			#simple_thread .post .avatar {
				margin-right: 12px
			}

			#simple_thread .nav-tab>a {
				color: #7f919e;
				display: block;
				margin: 0;
				padding: 0;
				font-weight: 700;
				line-height: 1;
				position: relative;
				transition: all .2s ease-in-out
			}

			#simple_thread .tab-conversation>a {
				text-transform: capitalize;
				font-size: 15px;
				padding: 12px 0;
				margin-right: 15px
			}

			#simple_thread .btn:hover {
				background: #606d75;
				background: rgba(29, 47, 58, .7);
				color: #fff
			}

			#simple_thread .btn.active,
			#simple_thread .btn:active {
				transition: none;
				background: #2e9fff
			}

			#simple_thread .btn.busy {
				background: #ebeef2;
				color: #999;
				text-shadow: none
			}

			#simple_thread .children .show-children-wrapper {
				margin-bottom: 24px
			}

			#simple_thread .children .show-children {
				margin-left: 60px;
				font-size: 13px;
				line-height: 15px;
				color: #656c7a;
				text-decoration: underline
			}

			#simple_thread .post-content .indicator {
				position: absolute;
				top: 0;
				left: 0;
				width: 5px;
				height: 48px;
				border-radius: 3px
			}

			#simple_thread .post-content.target {
				padding-left: 12px
			}

			#simple_thread .tab-conversation.active>a {
				color: #2a2e2e !important
			}

			#simple_thread .post-body a[data-dsq-mention] {
				font-weight: 700
			}

			#simple_thread .tab-conversation.active>a:after {
				content: " ";
				display: block;
				height: 2px;
				background: #2e9fff;
				position: absolute;
				bottom: -2px;
				left: 0;
				right: 0
			}

			#simple_thread .post-body a[data-dsq-mention]:before {
				content: '@'
			}

			#simple_thread .btn.busy:active,
			#simple_thread .btn.busy:hover {
				background: #ebeef2;
				text-shadow: none;
				cursor: not-allowed
			}

			#simple_thread .post-content.target>.avatar {
				left: 12px
			}

			#simple_thread .post-content.target .indicator {
				background: #ffc62e
			}

			#simple_thread .post-header {
				line-height: 1;
				font-size: 13px;
				padding-right: 46px;
				margin-bottom: 3px
			}

			#simple_thread .post-meta {
				display: inline-block
			}

			#simple_thread .load-more {
				margin: 0 0 24px
			}

			#simple_thread .post-body spoiler {
				display: inline;
				background: #7f919e;
				color: transparent;
				padding: 0 .5em
			}

			#simple_thread .post-header a {
				color: #7f919e;
				line-height: 1
			}

			#simple_thread .post-body-inner p {
				font-size: 15px;
				line-height: 21px;
				margin: 0 0 15px;
				word-wrap: break-word
			}

			#simple_thread .media a {
				margin-right: 10px
			}

			#simple_thread .post-header .author {
				color: #656c7a;
				font-weight: 700
			}

			#simple_thread .post-header .time-ago,
			#simple_thread .post-header .reply {
				font-weight: 500;
				font-size: 12px;
				color: #656c7a
			}

			#simple_thread .post-meta .bullet {
				padding: 0;
				color: #c2c6cc;
				line-height: 1.4
			}

			#simple_thread .children .post {
				margin-left: 60px
			}

			#simple_thread .load-more .btn {
				font-size: 13px;
				font-weight: 400;
				display: block;
				text-align: center;
				padding: 11px 14px
			}

			#simple_thread.mobile .post-header {
				padding-right: 0;
				margin-bottom: 4px;
				font-size: 14px;
				line-height: 18px;
				position: relative;
				top: -4px
			}

			#simple_thread.mobile .post-body-inner {
				clear: left;
				position: relative;
				top: -4px;
				overflow: visible
			}

			#simple_thread.mobile .post-body {
				display: block;
				overflow: visible
			}

			#simple_thread .post-body spoiler:hover,
			#simple_thread .post-body spoiler:focus {
				background: #e7e9ee;
				color: inherit
			}

			#simple_thread .post-body-inner p:last-child {
				margin: 0
			}

			#simple_thread.mobile .avatar img {
				width: 30px;
				height: 30px
			}

			#simple_thread .post-header .time-ago:hover,
			#simple_thread .post-header .reply:hover {
				color: #2a2e2e
			}

			#simple_thread .children .post .indicator {
				height: 36px
			}

			#simple_thread .children .children .post,
			#simple_thread .children .children .show-children {
				margin-left: 48px
			}

			#simple_thread.mobile .post-header .post-byline {
				display: block;
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
				padding-right: 15px
			}

			#simple_thread.mobile .post-header .author {
				font-size: 15px;
				line-height: 18px
			}

			#simple_thread.mobile .post-meta .bullet-first {
				display: none
			}

			#simple_thread.mobile .children .show-children {
				margin-left: 0
			}

			#simple_thread.mobile .tab-conversation.active>a>span {
				display: none
			}

			#simple_thread .post.minimized>.post-content .post-body-inner {
				opacity: .7;
				font-size: 12px;
				line-height: 36px
			}

			#simple_thread .post.minimized>.post-content .post-header {
				display: none
			}

			#simple_thread.mobile .post-list .post .post-content {
				margin-bottom: 16px;
				transition: none
			}

			#simple_thread.mobile .post-list .post .children,
			#simple_thread.mobile .children .children .show-children {
				padding-left: 17px;
				border-left: 2px solid #e7e9ee
			}

			#simple_thread .post.minimized>.post-content .avatar img,
			#simple_thread .children .post .avatar .user img {
				width: 36px;
				height: 36px
			}

			#simple_thread .post.minimized>.post-content .avatar img {
				border-radius: 2px
			}

			#simple_thread .children .children .children .children .post {
				margin-left: 0
			}

			#simple_thread.mobile .post-list .post .post-content .indicator {
				height: 30px
			}

			#simple_thread.mobile .post-list .post .children .post {
				margin-left: 0
			}

			#simple_thread.mobile .post-list .post.minimized>.post-content {
				margin-bottom: 12px
			}

			#simple_thread.mobile .post-list .post .post-content .avatar img {
				width: 30px;
				height: 30px
			}

			#simple_thread.mobile .post-list .post .children li:only-child {
				margin-bottom: 20px
			}

			#simple_thread .children .children .children .children .post .post-body {
				margin-left: 48px
			}

			#simple_thread .children .children .children .children .post .indicator {
				left: 0
			}

			#simple_thread.mobile .post-list .post .post-content.target .avatar {
				margin-left: 8px
			}

			#simple_thread.mobile .post-list .post .children .children .children {
				padding-left: 0;
				border-left: none
			}

			#simple_thread.mobile .post-list .post.minimized>.post-content .post-body-inner {
				clear: none
			}

			#simple_thread.mobile .post-list .post .children .post .post-content .post-body {
				margin-left: 0
			}
		</style>
		<link rel="amphtml" href="https://imququ.com/amp/post/web-proxy-2.html">
		<meta name="description"
			content="上篇文章里，我介绍了 HTTP 代理的两种形式，并用 Node.js 实现了一个可用的普通 / 隧道代理。今天这篇文章介绍如何将浏览器与代理之间的流量传输升级为 HTTPS。">
		<meta name="twitter:card" content="summary">
		<meta name="twitter:site" content="@qgy18">
		<meta name="twitter:title" content="HTTP 代理原理及实现（二） | JerryQu 的小站">
		<meta name="twitter:description"
			content="上篇文章里，我介绍了 HTTP 代理的两种形式，并用 Node.js 实现了一个可用的普通 / 隧道代理。今天这篇文章介绍如何将浏览器与代理之间的流量传输升级为 HTTPS。">
		<meta name="twitter:image" content="https://st.imququ.com/static/img/blog/ququ_avatar.jpg">
	</head>
	<body>
		<div class="container">
			<div class="left-col">
				<div class="intrude-less">
					<header id="header" class="inner">
						<div class="profilepic"> <a href="https://imququ.com/" aria-label="Home"></a></div>
						<h1><a href="https://imququ.com/">Jerry Qu</a></h1>
						<p class="subtitle"> 专注 WEB 端开发</p>
						<nav id="main-nav">
							<ul>
								<li><a href="https://imququ.com/"><span>首页</span></a> </li>
								<li><a href="https://imququ.com/post/series.html"><span>专题</span></a> </li>
								<li><a href="https://imququ.com/post/archives.html"><span>归档</span></a> </li>
								<li><a href="https://imququ.com/post/blogroll.html"><span>友链</span></a> </li>
								<li><a href="https://imququ.com/post/about.html"><span>关于</span></a> </li>
							</ul>
						</nav>
						<nav id="sub-nav">
							<div class="social"> <a class="twitter external" rel="nofollow"
									href="https://twitter.com/qgy18" title="Twitter" aria-label="Twitter">Twitter</a><a
									class="rss" href="https://imququ.com/rss.html" title="RSS 订阅"
									aria-label="RSS 订阅">RSS</a><a class="search" href="https://imququ.com/search.html"
									title="站内搜索" aria-label="站内搜索">Search</a></div>
						</nav>
					</header>
				</div>
			</div>
			<div class="mid-col">
				<div class="mid-col-container">
					<div id="content" class="inner"><s> </s>
						<script type="application/ld+json">
							{
								"@context": "http://schema.org",
								"@type": "BlogPosting",
								"mainEntityOfPage": "https://imququ.com/post/web-proxy-2.html",
								"headline": "HTTP 代理原理及实现（二）",
								"datePublished": "2015-11-20T23:51:38+08:00",
								"dateModified": "2015-11-20T23:51:38+08:00",
								"author": {
									"@type": "Person",
									"name": "JerryQu"
								},
								"publisher": {
									"@type": "Organization",
									"name": "JerryQu 的小站",
									"logo": {
										"@type": "ImageObject",
										"url": "https://st.imququ.com/static/img/blog/banner.png",
										"width": 600,
										"height": 60
									}
								},
								"image": {
									"@type": "ImageObject",
									"url": "https://imququ.com/i/resize/static/uploads/2015/11/fake_certificate.png",
									"width": 1200,
									"height": 800
								}
							}
						</script>
						<article class="post post-214">
							<div class="meta">
								<div class="date"> <time>Nov 20, 2015</time></div>
								<div class="date-modified"> <time>Nov 20, 2015</time></div>
								<div class="comment"> <a href="https://imququ.com/post/web-proxy-2.html#comments">20
										Comments</a></div>
							</div>
							<h1 class="title">HTTP 代理原理及实现（二）</h1>
							<div class="entry-content">
								<p class="expired-tips"> 提醒：本文最后更新于&nbsp;2402&nbsp;天前，文中所描述的信息可能已发生改变，请谨慎使用。</p>
								<p>在上篇《<a href="https://imququ.com/post/web-proxy.html">HTTP 代理原理及实现（一）</a>》里，我介绍了 HTTP
									代理的两种形式，并用 Node.js 实现了一个可用的普通 / 隧道代理。普通代理可以用来承载 HTTP 流量；隧道代理可以用来承载任何 TCP 流量，包括 HTTP
									和 HTTPS。今天这篇文章介绍剩余部分：如何将浏览器与代理之间的流量传输升级为 HTTPS。</p>
								<p>上篇文章中实现的代理，是一个标准的 HTTP 服务，针对浏览器的普通请求和 <code>CONNECT</code> 请求，进行不同的处理。Node.js 为创建
									HTTP 或 HTTPS Server 提供了高度一致的接口，要将 HTTP 服务升级为 HTTPS 特别方便，只有一点点准备工作要做。</p>
								<p>我们知道 TLS 有三大功能：内容加密、身份认证和数据完整性。其中内容加密依赖于密钥协商机制；数据完整性依赖于 MAC（Message authentication
									code）校验机制；而身份认证则依赖于证书认证机制。一般操作系统或浏览器会维护一个受信任根证书列表，包含在列表之中的证书，或者由列表中的证书签发的证书都会被客户端信任。
								</p>
								<p>提供 HTTPS 服务的证书可以自己生成，然后手动加入到系统根证书列表中。但是对外提供服务的 HTTPS 网站，不可能要求每个用户都手动导入你的证书，所以更常见的做法是向
									CA（Certificate Authority，证书颁发机构）申请。根据证书的不同级别，CA 会进行不同级别的验证，验证通过后 CA
									会用他们的证书签发网站证书，这个过程通常是收费的（有免费的证书，最近免费的 <a href="https://letsencrypt.org/">Let's
										Encrypt</a> 也很火，这里不多介绍）。由于 CA 使用的证书都是由广泛内置在各系统中的根证书签发，所以从 CA 获得的网站证书会被绝大部分客户端信任。
								</p>
								<p>通过 CA 申请证书很简单，本文为了方便演示，采用自己签发证书的偷懒办法。现在广泛使用的证书是 x509.v3 格式，使用以下命令可以创建：</p>
								<pre><code class="lang-bash">openssl genrsa -out private.pem <span class="hljs-number">2048</span>
openssl req -new -x509 -key private.pem -out public.crt -days <span class="hljs-number">99999</span>
</code></pre>
								<p>第二行命令运行后，需要填写一些证书信息。需要注意的是 <code>Common Name</code> 一定要填写后续提供 HTTPS 服务的域名或
									IP。例如你打算在本地测试，<code>Common Name</code> 可以填写 <code>127.0.0.1</code>。证书创建好之后，再将
									<code>public.crt</code> 添加到系统受信任根证书列表中。为了确保添加成功，可以用浏览器验证一下：
								</p>
								<p><img alt="fake_certificate" itemprop="image" width="484" height="244"
										src="./HTTP 代理原理及实现（二） _ JerryQu 的小站_files/fake_certificate.png.webp"
										class="loaded"></p>
								<p>接着，可以改造之前的 Node.js 代码了，需要改动的地方不多：</p>
								<pre><b class="name">JS</b><code class="lang-js"><span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);
<span class="hljs-keyword">var</span> https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>);
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">var</span> net = <span class="hljs-built_in">require</span>(<span class="hljs-string">'net'</span>);
<span class="hljs-keyword">var</span> url = <span class="hljs-built_in">require</span>(<span class="hljs-string">'url'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">request</span><span class="hljs-params">(cReq, cRes)</span> </span>{
    <span class="hljs-keyword">var</span> u = url.parse(cReq.url);

    <span class="hljs-keyword">var</span> options = {
        hostname : u.hostname, 
        port     : u.port || <span class="hljs-number">80</span>,
        path     : u.path,       
        method     : cReq.method,
        headers     : cReq.headers
    };

    <span class="hljs-keyword">var</span> pReq = http.request(options, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(pRes)</span> </span>{
        cRes.writeHead(pRes.statusCode, pRes.headers);
        pRes.pipe(cRes);
    }).on(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span> </span>{
        cRes.end();
    });

    cReq.pipe(pReq);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connect</span><span class="hljs-params">(cReq, cSock)</span> </span>{
    <span class="hljs-keyword">var</span> u = url.parse(<span class="hljs-string">'http://'</span> + cReq.url);

    <span class="hljs-keyword">var</span> pSock = net.connect(u.port, u.hostname, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
        cSock.write(<span class="hljs-string">'HTTP/1.1 200 Connection Established\r\n\r\n'</span>);
        pSock.pipe(cSock);
    }).on(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span> </span>{
        cSock.end();
    });

    cSock.pipe(pSock);
}

<span class="hljs-keyword">var</span> options = {
    key: fs.readFileSync(<span class="hljs-string">'./private.pem'</span>),
    cert: fs.readFileSync(<span class="hljs-string">'./public.crt'</span>)
};

https.createServer(options)
    .on(<span class="hljs-string">'request'</span>, request)
    .on(<span class="hljs-string">'connect'</span>, connect)
    .listen(<span class="hljs-number">8888</span>, <span class="hljs-string">'0.0.0.0'</span>);
</code></pre>
								<p>可以看到，除了将 <code>http.createServer</code> 换成
									<code>https.createServer</code>，增加证书相关配置之外，这段代码没有任何改变。这也是引入 TLS
									层的妙处，应用层不需要任何改动，就能获得诸多安全特性。
								</p>
								<p>运行服务后，只需要将浏览器的代理设置为 <code>HTTPS 127.0.0.1:8888</code> 即可，功能照旧。这样改造，只是将浏览器到代理之间的流量升级为了
									HTTPS，代理自身逻辑、与服务端的通讯方式，都没有任何变化。</p>
								<p>最后，还是写段 Node.js 代码验证下这个 HTTPS 代理服务：</p>
								<pre><b class="name">JS</b><code class="lang-js"><span class="hljs-keyword">var</span> https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>);

<span class="hljs-keyword">var</span> options = {
    hostname : <span class="hljs-string">'127.0.0.1'</span>,
    port     : <span class="hljs-number">8888</span>,
    path     : <span class="hljs-string">'imququ.com:80'</span>,
    method     : <span class="hljs-string">'CONNECT'</span>
};

<span class="hljs-comment">//禁用证书验证，不然自签名的证书无法建立 TLS 连接</span>
process.env.NODE_TLS_REJECT_UNAUTHORIZED = <span class="hljs-string">"0"</span>;

<span class="hljs-keyword">var</span> req = https.request(options);

req.on(<span class="hljs-string">'connect'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(res, socket)</span> </span>{
    socket.write(<span class="hljs-string">'GET / HTTP/1.1\r\n'</span> +
                 <span class="hljs-string">'Host: imququ.com\r\n'</span> +
                 <span class="hljs-string">'Connection: Close\r\n'</span> +
                 <span class="hljs-string">'\r\n'</span>);

    socket.on(<span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(chunk)</span> </span>{
        <span class="hljs-built_in">console</span>.log(chunk.toString());
    });

    socket.on(<span class="hljs-string">'end'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'socket end.'</span>);
    });
});

req.end();
</code></pre>
								<p>这段代码和上篇文章最后那段的区别只是 <code>http.request</code> 换成了
									<code>https.request</code>，运行结果完全一样，这里就不贴了。本文所有代码可以从这个仓库获得：<a
										href="https://github.com/qgy18/proxy-demo">proxy-demo</a>。
								</p>
								<p>本文就写到这里，大家有什么问题欢迎给我评论留言。</p>
								<p> 本文链接：<a rel="bookmark" title="Permalink to HTTP 代理原理及实现（二）"
										href="https://imququ.com/post/web-proxy-2.html">https://imququ.com/post/web-proxy-2.html</a>，<a
										href="https://imququ.com/post/web-proxy-2.html#comments">参与评论 »</a></p>
								<p>--<acronym title="End of File">EOF</acronym>--</p>
								<p class="post-info"> 发表于&nbsp;<span class="date">2015-11-20 23:51:38</span> ，并被添加「 <a
										href="https://imququ.com/search.html?s=tag%3ANode">Node</a> 、 <a
										href="https://imququ.com/search.html?s=tag%3AProxy">Proxy</a> 、 <a
										href="https://imququ.com/search.html?s=tag%3AHTTPS">HTTPS</a> 」标签 。<a
										href="https://imququ.com/post/web-proxy-2.md">查看本文 Markdown 版本 »</a></p>
								<p class="copyright-info">本站使用「<a
										href="http://creativecommons.org/licenses/by/4.0/deed.zh">署名 4.0
										国际</a>」创作共享协议，<a href="https://imququ.com/post/about.html#toc-1">相关说明 »</a></p>
								<p class="expired-tips"> 提醒：本文最后更新于&nbsp;2402&nbsp;天前，文中所描述的信息可能已发生改变，请谨慎使用。</p>
								<div class="entry-series">
									<h3>专题「HTTP 相关」的其他文章&nbsp;<a href="https://imququ.com/series.html#toc-7"
											title="更多">»</a></h3>
									<ul>
										<li><a href="https://imququ.com/post/http-alt-svc.html">HTTP Alternative
												Services 介绍</a>&nbsp;<span class="date">(Aug 21, 2016)</span> </li>
										<li><a href="https://imququ.com/post/sth-about-switch-to-https-3.html">关于启用
												HTTPS 的一些经验分享（三）</a>&nbsp;<span class="date">(May 05, 2016)</span> </li>
										<li><a href="https://imququ.com/post/how-to-compress-http-request-body.html">如何压缩
												HTTP 请求正文</a>&nbsp;<span class="date">(Apr 18, 2016)</span> </li>
										<li><a href="https://imququ.com/post/content-encoding-header-in-http.html">HTTP
												协议中的 Content-Encoding</a>&nbsp;<span class="date">(Apr 17, 2016)</span>
										</li>
										<li><a href="https://imququ.com/post/how-to-decrypt-https.html">三种解密 HTTPS
												流量的方法介绍</a>&nbsp;<span class="date">(Mar 28, 2016)</span> </li>
										<li><a href="https://imququ.com/post/http-public-key-pinning.html">HTTP Public
												Key Pinning 介绍</a>&nbsp;<span class="date">(Mar 05, 2016)</span> </li>
										<li><a href="https://imququ.com/post/sth-about-switch-to-https-2.html">关于启用
												HTTPS 的一些经验分享（二）</a>&nbsp;<span class="date">(Dec 22, 2015)</span> </li>
										<li><a href="https://imququ.com/post/sth-about-switch-to-https.html">关于启用 HTTPS
												的一些经验分享（一）</a>&nbsp;<span class="date">(Dec 04, 2015)</span> </li>
										<li><a href="https://imququ.com/post/web-proxy.html">HTTP
												代理原理及实现（一）</a>&nbsp;<span class="date">(Nov 20, 2015)</span> </li>
										<li><a href="https://imququ.com/post/content-security-policy-level-2.html">Content
												Security Policy Level 2 介绍</a>&nbsp;<span class="date">(Oct 05,
												2015)</span> </li>
									</ul>
								</div>
							</div>
						</article>
						<nav class="page-navi"> <a href="https://imququ.com/post/web-proxy.html"
								class="prev">«&nbsp;HTTP 代理原理及实现（一）</a> <a
								href="https://imququ.com/post/http2-new-opportunities-and-challenges.html"
								class="next">HTTP/2：新的机遇与挑战&nbsp;»</a> </nav>
						<section id="comments">
							<h1 class="title">Comments</h1>
							<div class="total_thread" data-identifier="post-web-proxy-2"
								data-url="https://imququ.com/post/web-proxy-2.html">
								<div id="simple_thread" data-thread="4680748917" data-identifier="post-web-proxy-2">
									<div class="thread">
										<header>
											<nav class="nav clearfix">
												<ul>
													<li class="nav-tab tab-conversation active"><a
															class="publisher-nav-color"><span>20 </span>Comments</a>
													</li>
												</ul>
											</nav>
										</header>
										<section>
											<div class="thread-new"><button class="create-post">点击发表新评论</button><span
													class="tips"><a
														href="https://imququ.com/post/web-proxy-2.html#reload"
														class="reload"
														title="系统检测你可能无法访问 Disqus 服务，已自动显示为评论基础模式。如需完整体验请针对 disq.us | disquscdn.com | disqus.com 启用代理~">尝试评论完整模式</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a
														href="https://imququ.com/post/web-proxy-2.html#reload"
														class="reload-and-skip-check"
														title="如果你确定代理工作正常，但仍然无法加载评论完整模式，请点击这里跳过评论可用性检测逻辑。">强制使用评论完整模式</a></span>
											</div>
										</section>
										<section class="thread-post-list">
											<ul class="post-list" data-id="0">
												<li class="post " id="post-5109631977">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><img
																	data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color">kajweb</span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="5109631977"
																		href="https://imququ.com/post/web-proxy-2.html#comment-5109631977"
																		class="time-ago">2年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="5109631977">回复</a></span></header>
															<div class="post-body-inner">
																<p>2020年10月，openssl req -new -x509 -key private.pem -out
																	public.crt -days 99999在Chrome已经无法正常使用。需要配置CAN</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="5109631977"></ul>
												</li>
												<li class="post " id="post-4411750902">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><a
																	href="https://disqus.com/by/gy_li/"><img
																		data-src="https://c.disquscdn.com/uploads/users/33095/1716/avatar92.jpg?1554534966"></a>
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color"><a
																			href="https://disqus.com/by/gy_li/">gy
																			li</a></span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="4411750902"
																		href="https://imququ.com/post/web-proxy-2.html#comment-4411750902"
																		class="time-ago">3年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="4411750902">回复</a></span></header>
															<div class="post-body-inner">
																<p>HTTP 代理原理及实现（二）,
																	这篇文章，作者的理解有误。这种不能叫做https代理，而且这样方式也不能代理访问https的网站。文章（一）说的是没错的，文章（二）实际是通过https访问一个web，并不是可用的https代理方式。
																</p>
																<p>正确的应该是 浏览器 &lt;==&gt; stunnel客户端
																	&lt;=(ssl/https)=&gt; stunnel服务端 &lt;==&gt;
																	http/https proxy &lt;==&gt; 网站。</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="4411750902">
														<li class="post " id="post-5501252357">
															<div class="post-content clearfix">
																<div class="indicator"></div>
																<div class="avatar">
																	<div class="user"><a
																			href="https://disqus.com/by/JerryQu/"><img
																				data-src="https://c.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1654684055"></a>
																	</div>
																</div>
																<div class="post-body">
																	<header class="post-header"><span
																			class="post-byline"><span
																				class="author publisher-anchor-color"><a
																					href="https://disqus.com/by/JerryQu/">Jerry
																					Qu</a></span></span><span
																			class="post-meta"><span
																				class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																				data-id="5501252357"
																				href="https://imququ.com/post/web-proxy-2.html#comment-5501252357"
																				class="time-ago">10个月前</a><span
																				class="bullet">&nbsp;•&nbsp;</span><a
																				href="https://imququ.com/post/web-proxy-2.html#"
																				class="reply" data-next=""
																				data-id="5501252357">回复</a></span>
																	</header>
																	<div class="post-body-inner">
																		<p>这篇文章写于6年前，当初叫HTTPS代理确实不准确。置顶这条评论，供参考~</p>
																	</div>
																</div>
															</div>
															<ul class="children" data-id="5501252357"></ul>
														</li>
													</ul>
												</li>
												<li class="post " id="post-3058566338">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><img
																	data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color">jim</span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="3058566338"
																		href="https://imququ.com/post/web-proxy-2.html#comment-3058566338"
																		class="time-ago">6年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="3058566338">回复</a></span></header>
															<div class="post-body-inner">
																<p>写的不错，赞一个！</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="3058566338"></ul>
												</li>
												<li class="post " id="post-2882087202">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><a
																	href="https://disqus.com/by/szmtcjm/"><img
																		data-src="https://c.disquscdn.com/uploads/users/9862/7123/avatar92.jpg?1473314225"></a>
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color"><a
																			href="https://disqus.com/by/szmtcjm/">szmtcjm</a></span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="2882087202"
																		href="https://imququ.com/post/web-proxy-2.html#comment-2882087202"
																		class="time-ago">6年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="2882087202">回复</a></span></header>
															<div class="post-body-inner">
																<p>博主你好，设置pac后，如果是https的话，浏览器一定会走隧道代理吗，不能改为前一篇文章中的第一种代理吗
																</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="2882087202"></ul>
												</li>
												<li class="post " id="post-2586664467">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><a
																	href="https://disqus.com/by/disqus_wNIuNc4KNV/"><img
																		data-src="//a.disquscdn.com/1647409581/images/noavatar92.png"></a>
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color"><a
																			href="https://disqus.com/by/disqus_wNIuNc4KNV/">HelloCode</a></span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="2586664467"
																		href="https://imququ.com/post/web-proxy-2.html#comment-2586664467"
																		class="time-ago">6年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="2586664467">回复</a></span></header>
															<div class="post-body-inner">
																<p>您好，我想请教一下：如果这个代理要破解客户端的通信数据，要如何实现呢？</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="2586664467"></ul>
												</li>
												<li class="post " id="post-2529564869">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><img
																	data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color">Alan</span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="2529564869"
																		href="https://imququ.com/post/web-proxy-2.html#comment-2529564869"
																		class="time-ago">6年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="2529564869">回复</a></span></header>
															<div class="post-body-inner">
																<p>楼主这段https proxy的代码我貌似跑不起来。</p>
																<p>1. 已经将self-signed certificate加入系统信任列表<br>测试直接访问node
																	proxy server有效</p>
																<p>2. 将chrome的proxy (也就是mac的system proxy)设置为127.0.0.1:
																	9527以后，用chrome访问github无法获得响应。<br>debug发现代码里的request和connect
																	function都没有被call。</p>
																<p>是我有什么地方没弄对吗？</p>
																<p class="media"><a
																		href="https://a.disquscdn.com/uploads/mediaembed/images/3247/6110/original.jpg"
																		target="_blank">[图片]</a><a
																		href="https://a.disquscdn.com/uploads/mediaembed/images/3247/6111/original.jpg"
																		target="_blank">[图片]</a></p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="2529564869">
														<li class="post " id="post-2531187549">
															<div class="post-content clearfix">
																<div class="indicator"></div>
																<div class="avatar">
																	<div class="user"><img
																			data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
																	</div>
																</div>
																<div class="post-body">
																	<header class="post-header"><span
																			class="post-byline"><span
																				class="author publisher-anchor-color">alan</span></span><span
																			class="post-meta"><span
																				class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																				data-id="2531187549"
																				href="https://imququ.com/post/web-proxy-2.html#comment-2531187549"
																				class="time-ago">6年前</a><span
																				class="bullet">&nbsp;•&nbsp;</span><a
																				href="https://imququ.com/post/web-proxy-2.html#"
																				class="reply" data-next=""
																				data-id="2531187549">回复</a></span>
																	</header>
																	<div class="post-body-inner">
																		<p>经过一些折腾，用的是SwitchyOmega终于跑通了，两个问题:<br>1.
																			证书必须是pem格式，用例子里的public.crt, chrome会报错:
																			ERR_PROXY_CERTIFICATE_INVALID<br>2.
																			MAC的系统proxy设置貌似还是有问题，有待研究</p>
																	</div>
																</div>
															</div>
															<ul class="children" data-id="2531187549"></ul>
														</li>
														<li class="post " id="post-2530356670">
															<div class="post-content clearfix">
																<div class="indicator"></div>
																<div class="avatar">
																	<div class="user"><a
																			href="https://disqus.com/by/JerryQu/"><img
																				data-src="https://c.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1654684055"></a>
																	</div>
																</div>
																<div class="post-body">
																	<header class="post-header"><span
																			class="post-byline"><span
																				class="author publisher-anchor-color"><a
																					href="https://disqus.com/by/JerryQu/">Jerry
																					Qu</a></span></span><span
																			class="post-meta"><span
																				class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																				data-id="2530356670"
																				href="https://imququ.com/post/web-proxy-2.html#comment-2530356670"
																				class="time-ago">6年前</a><span
																				class="bullet">&nbsp;•&nbsp;</span><a
																				href="https://imququ.com/post/web-proxy-2.html#"
																				class="reply" data-next=""
																				data-id="2530356670">回复</a></span>
																	</header>
																	<div class="post-body-inner">
																		<p>Chrome 的 Proxy 应该设置为 HTTPS 远程IP:端口 这种形式啊。我用的
																			SwitchyOmega 这个扩展：</p>
																		<p class="media"><a
																				href="https://a.disquscdn.com/uploads/mediaembed/images/3249/7107/original.jpg"
																				target="_blank">[图片]</a></p>
																	</div>
																</div>
															</div>
															<ul class="children" data-id="2530356670">
																<li class="post " id="post-2530541409">
																	<div class="post-content clearfix">
																		<div class="indicator"></div>
																		<div class="avatar">
																			<div class="user"><img
																					data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
																			</div>
																		</div>
																		<div class="post-body">
																			<header class="post-header"><span
																					class="post-byline"><span
																						class="author publisher-anchor-color">alan</span></span><span
																					class="post-meta"><span
																						class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																						data-id="2530541409"
																						href="https://imququ.com/post/web-proxy-2.html#comment-2530541409"
																						class="time-ago">6年前</a><span
																						class="bullet">&nbsp;•&nbsp;</span><a
																						href="https://imququ.com/post/web-proxy-2.html#"
																						class="reply" data-next=""
																						data-id="2530541409">回复</a></span>
																			</header>
																			<div class="post-body-inner">
																				<p>mac
																					里chrome默认调用系统proxy设置。回头用这个插件试试。还有是不是示例代码需要connect方法先建立TCP
																					tunnel，并不是可以设置代理后直接访问？</p>
																				<p class="media"><a
																						href="https://a.disquscdn.com/uploads/mediaembed/images/3250/1354/original.jpg"
																						target="_blank">[图片]</a></p>
																			</div>
																		</div>
																	</div>
																	<ul class="children" data-id="2530541409"></ul>
																</li>
															</ul>
														</li>
														<li class="post " id="post-2529601726">
															<div class="post-content clearfix">
																<div class="indicator"></div>
																<div class="avatar">
																	<div class="user"><img
																			data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
																	</div>
																</div>
																<div class="post-body">
																	<header class="post-header"><span
																			class="post-byline"><span
																				class="author publisher-anchor-color">alan</span></span><span
																			class="post-meta"><span
																				class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																				data-id="2529601726"
																				href="https://imququ.com/post/web-proxy-2.html#comment-2529601726"
																				class="time-ago">6年前</a><span
																				class="bullet">&nbsp;•&nbsp;</span><a
																				href="https://imququ.com/post/web-proxy-2.html#"
																				class="reply" data-next=""
																				data-id="2529601726">回复</a></span>
																	</header>
																	<div class="post-body-inner">
																		<p>用client代码测试得到socket hang up 的error:</p>
																		<p>events.js:154</p>
																		<p> throw er; // Unhandled 'error' event</p>
																		<p> ^</p>
																		<p>Error: socket hang up</p>
																		<p> at createHangUpError
																			(_http_client.js:206:15)</p>
																		<p> at TLSSocket.socketOnEnd
																			(_http_client.js:298:23)</p>
																		<p> at emitNone (events.js:85:20)</p>
																		<p> at TLSSocket.emit (events.js:179:7)</p>
																		<p> at endReadableNT
																			(_stream_readable.js:906:12)</p>
																		<p> at nextTickCallbackWith2Args (node.js:475:9)
																		</p>
																		<p> at process._tickCallback (node.js:389:17)
																		</p>
																	</div>
																</div>
															</div>
															<ul class="children" data-id="2529601726"></ul>
														</li>
													</ul>
												</li>
												<li class="post " id="post-2522596507">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><img
																	data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color">cloudop</span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="2522596507"
																		href="https://imququ.com/post/web-proxy-2.html#comment-2522596507"
																		class="time-ago">6年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="2522596507">回复</a></span></header>
															<div class="post-body-inner">
																<p>hi,博主，我想请问下，这个https连接的代理，用在pac文件里的话要怎么写呢。一般pac里面写的是PROXY
																	<a href="http://disq.us/url?url=http%3A%2F%2Fxxx.xxx.xxx.xxx%3AvwIERIC947ylDrMJ6gfljBB5STc&amp;cuid=3833100"
																		rel="nofollow noopener"
																		title="xxx.xxx.xxx.xxx">xxx.xxx.xxx.xxx</a>:port;客户端与代理间通信升级成https后，写法应该是要改的吧？
																</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="2522596507">
														<li class="post " id="post-2522666123">
															<div class="post-content clearfix">
																<div class="indicator"></div>
																<div class="avatar">
																	<div class="user"><a
																			href="https://disqus.com/by/JerryQu/"><img
																				data-src="https://c.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1654684055"></a>
																	</div>
																</div>
																<div class="post-body">
																	<header class="post-header"><span
																			class="post-byline"><span
																				class="author publisher-anchor-color"><a
																					href="https://disqus.com/by/JerryQu/">Jerry
																					Qu</a></span></span><span
																			class="post-meta"><span
																				class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																				data-id="2522666123"
																				href="https://imququ.com/post/web-proxy-2.html#comment-2522666123"
																				class="time-ago">6年前</a><span
																				class="bullet">&nbsp;•&nbsp;</span><a
																				href="https://imququ.com/post/web-proxy-2.html#"
																				class="reply" data-next=""
																				data-id="2522666123">回复</a></span>
																	</header>
																	<div class="post-body-inner">
																		<p>我用的是 Chrome 的 SwitchyOmega 扩展，我看导出的 PAC
																			是这样的：<br>return "HTTPS <a
																				href="http://disq.us/url?url=http%3A%2F%2Fxxx.xxx.xxx.xxx%3A8080%3A7_a5f1RbEd7MukFE0mv9lh7lQh8&amp;cuid=3833100"
																				rel="nofollow noopener"
																				title="xxx.xxx.xxx.xxx:8080">xxx.xxx.xxx.xxx:8080</a>";
																		</p>
																	</div>
																</div>
															</div>
															<ul class="children" data-id="2522666123">
																<li class="post " id="post-2522734004">
																	<div class="post-content clearfix">
																		<div class="indicator"></div>
																		<div class="avatar">
																			<div class="user"><img
																					data-src="https://st.imququ.com/static/img/blog/default_avatar.png">
																			</div>
																		</div>
																		<div class="post-body">
																			<header class="post-header"><span
																					class="post-byline"><span
																						class="author publisher-anchor-color">cloudop</span></span><span
																					class="post-meta"><span
																						class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																						data-id="2522734004"
																						href="https://imququ.com/post/web-proxy-2.html#comment-2522734004"
																						class="time-ago">6年前</a><span
																						class="bullet">&nbsp;•&nbsp;</span><a
																						href="https://imququ.com/post/web-proxy-2.html#"
																						class="reply" data-next=""
																						data-id="2522734004">回复</a></span>
																			</header>
																			<div class="post-body-inner">
																				<p>原来如此。谢谢哈。ip暴露了。。。要不要改一改</p>
																			</div>
																		</div>
																	</div>
																	<ul class="children" data-id="2522734004">
																		<li class="post " id="post-2522735760">
																			<div class="post-content clearfix">
																				<div class="indicator"></div>
																				<div class="avatar">
																					<div class="user"><a
																							href="https://disqus.com/by/JerryQu/"><img
																								data-src="https://c.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1654684055"></a>
																					</div>
																				</div>
																				<div class="post-body">
																					<header class="post-header"><span
																							class="post-byline"><span
																								class="author publisher-anchor-color"><a
																									href="https://disqus.com/by/JerryQu/">Jerry
																									Qu</a></span></span><span
																							class="post-meta"><span
																								class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																								data-id="2522735760"
																								href="https://imququ.com/post/web-proxy-2.html#comment-2522735760"
																								class="time-ago">6年前</a><span
																								class="bullet">&nbsp;•&nbsp;</span><a
																								href="https://imququ.com/post/web-proxy-2.html#"
																								class="reply"
																								data-next=""
																								data-id="2522735760">回复</a></span>
																					</header>
																					<div class="post-body-inner">
																						<p>哈哈，改了。</p>
																					</div>
																				</div>
																			</div>
																			<ul class="children" data-id="2522735760">
																			</ul>
																		</li>
																	</ul>
																</li>
															</ul>
														</li>
													</ul>
												</li>
												<li class="post " id="post-2389049211">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><a
																	href="https://disqus.com/by/galenye/"><img
																		data-src="//a.disquscdn.com/1647409581/images/noavatar92.png"></a>
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color"><a
																			href="https://disqus.com/by/galenye/">galenye</a></span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="2389049211"
																		href="https://imququ.com/post/web-proxy-2.html#comment-2389049211"
																		class="time-ago">7年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="2389049211">回复</a></span></header>
															<div class="post-body-inner">
																<p>最后一段代码，代理和目标服务器之间还是要走的是HTTP？</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="2389049211">
														<li class="post " id="post-2389812065">
															<div class="post-content clearfix">
																<div class="indicator"></div>
																<div class="avatar">
																	<div class="user"><a
																			href="https://disqus.com/by/JerryQu/"><img
																				data-src="https://c.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1654684055"></a>
																	</div>
																</div>
																<div class="post-body">
																	<header class="post-header"><span
																			class="post-byline"><span
																				class="author publisher-anchor-color"><a
																					href="https://disqus.com/by/JerryQu/">Jerry
																					Qu</a></span></span><span
																			class="post-meta"><span
																				class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																				data-id="2389812065"
																				href="https://imququ.com/post/web-proxy-2.html#comment-2389812065"
																				class="time-ago">7年前</a><span
																				class="bullet">&nbsp;•&nbsp;</span><a
																				href="https://imququ.com/post/web-proxy-2.html#"
																				class="reply" data-next=""
																				data-id="2389812065">回复</a></span>
																	</header>
																	<div class="post-body-inner">
																		<p>那个示例目的是演示隧道代理。隧道代理中代理只负责建立浏览器到目标服务器之间的隧道
																			socket，有了隧道，可以认为浏览器和目标服务器直连。浏览器发出的数据，无论是
																			HTTP 还是 HTTPS，甚至其他 TCP，目标服务器都可以原样收到。</p>
																	</div>
																</div>
															</div>
															<ul class="children" data-id="2389812065">
																<li class="post " id="post-2390863533">
																	<div class="post-content clearfix">
																		<div class="indicator"></div>
																		<div class="avatar">
																			<div class="user"><a
																					href="https://disqus.com/by/galenye/"><img
																						data-src="//a.disquscdn.com/1647409581/images/noavatar92.png"></a>
																			</div>
																		</div>
																		<div class="post-body">
																			<header class="post-header"><span
																					class="post-byline"><span
																						class="author publisher-anchor-color"><a
																							href="https://disqus.com/by/galenye/">galenye</a></span></span><span
																					class="post-meta"><span
																						class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																						data-id="2390863533"
																						href="https://imququ.com/post/web-proxy-2.html#comment-2390863533"
																						class="time-ago">7年前</a><span
																						class="bullet">&nbsp;•&nbsp;</span><a
																						href="https://imququ.com/post/web-proxy-2.html#"
																						class="reply" data-next=""
																						data-id="2390863533">回复</a></span>
																			</header>
																			<div class="post-body-inner">
																				<p>把最后一段中的80改成443发现不可行 不太理解原因 可否解惑一下</p>
																			</div>
																		</div>
																	</div>
																	<ul class="children" data-id="2390863533">
																		<li class="post " id="post-2390903474">
																			<div class="post-content clearfix">
																				<div class="indicator"></div>
																				<div class="avatar">
																					<div class="user"><a
																							href="https://disqus.com/by/JerryQu/"><img
																								data-src="https://c.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1654684055"></a>
																					</div>
																				</div>
																				<div class="post-body">
																					<header class="post-header"><span
																							class="post-byline"><span
																								class="author publisher-anchor-color"><a
																									href="https://disqus.com/by/JerryQu/">Jerry
																									Qu</a></span></span><span
																							class="post-meta"><span
																								class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																								data-id="2390903474"
																								href="https://imququ.com/post/web-proxy-2.html#comment-2390903474"
																								class="time-ago">7年前</a><span
																								class="bullet">&nbsp;•&nbsp;</span><a
																								href="https://imququ.com/post/web-proxy-2.html#"
																								class="reply"
																								data-next=""
																								data-id="2390903474">回复</a></span>
																					</header>
																					<div class="post-body-inner">
																						<p>那个是要打开的目标服务器端口，如果打开的是 443
																							端口，socket.write('GET /
																							HTTP/1.1\r\n...')
																							这段报文就不能这么写，必须从 TLS 的 Client
																							Hello 开始，异常麻烦。</p>
																					</div>
																				</div>
																			</div>
																			<ul class="children" data-id="2390903474">
																			</ul>
																		</li>
																	</ul>
																</li>
															</ul>
														</li>
													</ul>
												</li>
												<li class="post " id="post-2380861030">
													<div class="post-content clearfix">
														<div class="indicator"></div>
														<div class="avatar">
															<div class="user"><a
																	href="https://disqus.com/by/amowu/"><img
																		data-src="https://c.disquscdn.com/uploads/users/1308/2129/avatar92.jpg?1586703835"></a>
															</div>
														</div>
														<div class="post-body">
															<header class="post-header"><span class="post-byline"><span
																		class="author publisher-anchor-color"><a
																			href="https://disqus.com/by/amowu/">Amo
																			Wu</a></span></span><span
																	class="post-meta"><span
																		class="bullet bullet-first">&nbsp;•&nbsp;</span><a
																		data-id="2380861030"
																		href="https://imququ.com/post/web-proxy-2.html#comment-2380861030"
																		class="time-ago">7年前</a><span
																		class="bullet">&nbsp;•&nbsp;</span><a
																		href="https://imququ.com/post/web-proxy-2.html#"
																		class="reply" data-next=""
																		data-id="2380861030">回复</a></span></header>
															<div class="post-body-inner">
																<p>學習了，感謝分享。</p>
															</div>
														</div>
													</div>
													<ul class="children" data-id="2380861030"></ul>
												</li>
											</ul>
											<div class="load-more"><a href="https://imququ.com/post/web-proxy-2.html#"
													class="btn" style="display: none;">Load more comments</a></div>
										</section>
									</div>
								</div>
							</div>
						</section>
					</div>
				</div>
				<footer id="footer" class="inner"> ©&nbsp;2022&nbsp;-&nbsp;JerryQu 的小站&nbsp;-&nbsp;<a target="_blank"
						rel="nofollow noopener" class="external beian"
						href="http://www.beian.miit.gov.cn/">京ICP备15046275号-1</a><br> Powered by&nbsp;<a
						href="https://imququ.com/post/readme.html">ThinkJS 3</a>&nbsp;&amp;&nbsp;<a target="_blank"
						rel="nofollow noopener" class="external"
						href="https://github.com/shashankmehta/greyshade">GreyShade</a></footer>
			</div>
		</div> <input type="hidden" id="CURRENT_PAGE" value="post-web-proxy-2"> <input type="hidden" id="CDN_DOMAIN"
			value="https://st.imququ.com">
		<script>
			LS.ls2html("stc_ana_js", "script", "v")
		</script>
		<script>
			LS.ls2html("stc_jq_js", "script", "v")
		</script>
		<script>
			LS.ls2html("stc_blog_js", "script", "v")
		</script>
	</body>
</html>
